"""
班级管理视图模块

该模块包含班级日常管理相关的视图函数和类，如考勤统计、生日提醒、
周/月分析等功能，为教师提供班级管理的数据可视化和操作界面。
"""
from django.shortcuts import render
from datetime import date, datetime, timedelta
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Count, Sum, F
from core.models.classinfo import ClassInfo
from core.models.student import Student
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from core.views.homework_views import BaseBootstrapForm
from core.utils import log_operation
from django.forms import ModelForm
from core.models import DisciplineType, DisciplineRecord, DisciplineAppeal
from core.models.honor import HonorType, HonorRecord
from core.models.leave_request import LeaveRequest
from django.urls import reverse_lazy
from core.models.daily_attendance import DailyAttendance
from core.models.student_class_enrollment import StudentClassEnrollment
from .utils import (
    get_no_homework_count, get_warning, get_classes,
    get_daily_attendance_and_task_stats, get_leave_and_discipline_counts,
    get_class_subjects, get_student_performance_stats, get_week_dates, get_target_date
)


"""
获取指定班级中当天生日的学生信息
"""
def get_birthday_by_classid(classid):
    """
    获取指定班级中当天生日的学生信息

    根据传入的班级 ID 获取该班级中当天生日的学生信息。
    如果未传入班级 ID，则获取当前用户管理班级中当天生日的学生信息。

    :param classid: 班级ID，可选
    :type classid: int or None
    :return: 当天生日的学生列表
    :rtype: django.db.models.QuerySet
    """
    # 注：函数参数中缺少request，但实现中使用了request，需要后续修正
    if classid:
        try:
            class_obj = ClassInfo.objects.get(id=classid)
            classes = [class_obj]
        except ClassInfo.DoesNotExist:
            classes = []
    else:
        # 注意：此处缺少request参数，实际使用时会报错，需要修正
        user = request.user
        classes = get_classes(user)
    
    today = datetime.now().date()
    # 筛选出指定班级中当天生日的学生
    birthday_students = Student.objects.filter(
        classes__in=classes,
        birthday__month=today.month,
        birthday__day=today.day
    ).prefetch_related('classes')  # 优化关联查询
    
    return birthday_students

"""
仪表盘视图 - 展示班级管理数据的仪表盘样式
"""
@login_required
def home_teacher_dashboard(request, class_id):
    """
    展示班级管理数据的仪表盘视图

    显示指定班级的各类管理数据，以仪表盘样式展示，包括考勤、作业、违纪等信息。

    :param request: 请求对象
    :type request: django.http.HttpRequest
    :param class_id: 班级ID
    :type class_id: int
    :return: 渲染后的仪表盘页面
    :rtype: django.http.HttpResponse
    """
    prev = request.GET.get('prev', 0)
    target_date_str = get_target_date(prev)
    target_date = datetime.strptime(target_date_str, '%Y-%m-%d').date()
    user = request.user
    classes = get_classes(user)
    
    # 使用传入的class_id查找班级
    try:
        current_class = ClassInfo.objects.get(id=class_id)
        classname = f"{current_class.grade.name}{current_class.name}"
        classid = class_id  # 保持参数一致性
    except ClassInfo.DoesNotExist:
        # 如果班级不存在，使用用户的第一个班级
        first_class = classes.first()
        if first_class:
            classname = f"{first_class.grade.name}{first_class.name}"
            classid = first_class.id
        else:
            classname = ''
            classid = 0
    
    # 优化查询：使用select_related减少数据库查询
    student_list = Student.objects.filter(classes__id=classid).prefetch_related('classes')
    
    late_list = []
    # 注意：循环中查询单个学生可能导致N+1问题，建议后续优化
    for stu in student_list:
        student = Student.objects.get(id=stu.id)
        no_homework_count=get_no_homework_count(student,'today')
        warning = get_warning(student,'today')
        late_list.append({
            'student_id':student.id,
            'name':student.name,
            'no_homework_count':no_homework_count,
            'warning':warning,
            'phonenumber':student.contact_info
        })
    birthday_list=get_birthday_by_classid(classid)   


    # 获取班级考勤数据
    attendance_data=get_class_attendace(classid, target_date)
    attendance_list=get_daily_attendance_and_task_stats(classid, target_date)
    leave_discipline = get_leave_and_discipline_counts(classid, target_date)
    subjects=get_class_subjects(classid,target_date_str)
    
    performance_stats=get_student_performance_stats(classid, target_date)
    
    # 获取最近7天的考勤统计
    seven_days_ago = target_date - timedelta(days=7)
    attendance_stats = DailyAttendance.objects.filter(
        student__classes__id=classid,
        date__gte=seven_days_ago,
        date__lte=target_date
    ).values('date').annotate(
        present=Count('id', filter=Q(morning_attendance=True) | Q(afternoon_attendance=True) | Q(evening_attendance=True)),
        absent=Count('id', filter=Q(morning_attendance=False) & Q(afternoon_attendance=False) & Q(evening_attendance=False))
    ).order_by('date')

    # 处理考勤数据为图表所需格式
    attendance_labels = [item['date'].strftime('%Y-%m-%d') for item in attendance_stats]
    present_data = [item['present'] for item in attendance_stats]
    absent_data = [item['absent'] for item in attendance_stats]

    # 添加考勤数据默认值
    if not attendance_labels:
        # 生成最近7天的日期标签
        attendance_labels = [(seven_days_ago + timedelta(days=i)).strftime('%Y-%m-%d') for i in range(7)]
        present_data = [0] * 7
        absent_data = [0] * 7
    
    return render(request, 'classmanage/dashboard.html', 
                            {"data":target_date_str,
                            'subjects':subjects,
                            'performance_stats':performance_stats,
                            'leave_discipline':leave_discipline,
                            'attendance_list':attendance_list,
                            'late_list':late_list,
                            'classname': classname,
                            'total_count':student_list.count(),
                            'classid':classid,
                            'strdate': target_date,
                            'weekday': {'Monday':'星期一','Tuesday':'星期二','Wednesday':'星期三','Thursday':'星期四','Friday':'星期五','Saturday':'星期六','Sunday':'星期日'}.get(target_date.strftime('%A'), '未知'),
                            'get_birthday_by_classid':birthday_list,
                            'attendance_labels': attendance_labels,
                            'present_data': present_data,
                            'absent_data': absent_data})

"""
日分析视图 - 展示班级日常管理数据
"""
@login_required
def day_manage(request, classid=1):
    """
    展示班级日常管理数据的视图

    显示指定班级的每日考勤、作业完成情况、迟到统计、
    生日提醒等日常管理数据，并支持日期切换。

    :param request: 请求对象
    :type request: django.http.HttpRequest
    :param classid: 班级ID，默认为1
    :type classid: int
    :return: 渲染后的日管理页面
    :rtype: django.http.HttpResponse
    """
    prev = request.GET.get('prev', 0)
    target_date_str = get_target_date(prev)
    target_date = datetime.strptime(target_date_str, '%Y-%m-%d').date()
    user = request.user
    classes = get_classes(user)
    first_class = classes.first()
    
    if first_class:
        classname = f"{first_class.grade.name}{first_class.name}"
        classid = first_class.id
    else:
        classname = ''
        classid = 0
    
    # 优化查询：使用select_related减少数据库查询
    student_list = Student.objects.filter(classes__in=classes).prefetch_related('classes')
    
    late_list = []
    # 注意：循环中查询单个学生可能导致N+1问题，建议后续优化
    for stu in student_list:
        student = Student.objects.get(id=stu.id)
        no_homework_count=get_no_homework_count(student,'today')
        warning = get_warning(student,'today')
        late_list.append({
            'student_id':student.id,
            'name':student.name,
            'no_homework_count':no_homework_count,
            'warning':warning,
            'phonenumber':student.contact_info
        })
    birthday_list=get_birthday_by_classid(classid)   


    late_list=get_class_attendace(classid, target_date)
    attendance_list=get_daily_attendance_and_task_stats(classid, target_date)
    leave_discipline = get_leave_and_discipline_counts(classid, target_date)
    subjects=get_class_subjects(classid,target_date)
    
    performance_stats=get_student_performance_stats(classid, target_date)
    
    return render(request, 'classmanage/dashboard.html', 
                            {"data":target_date_str,
                            'subjects':subjects,
                            'performance_stats':performance_stats,
                            'leave_discipline':leave_discipline,
                            'attendance_list':attendance_list,
                            'late_list':late_list,
                            'classname': classname,
                            'total_count':student_list.count(),
                            'classid':classid,
                            'strdate': target_date,
                            'weekday': {'Monday':'星期一','Tuesday':'星期二','Wednesday':'星期三','Thursday':'星期四','Friday':'星期五','Saturday':'星期六','Sunday':'星期日'}.get(target_date.strftime('%A'), '未知'),
                            'get_birthday_by_classid':birthday_list})


def get_class_attendace(classid, date):
    """
    统计指定班级在指定日期的各时间段迟到信息

    参数:
        classid (int): 班级ID
        date (date): 统计日期（格式：YYYY-MM-DD）

    返回:
        dict: 包含上午、下午、晚上迟到信息的字典
        格式示例: {
            'morning_late': 2,  # 上午迟到人数
            'afternoon_late': 1,  # 下午迟到人数
            'evening_late': 0  # 晚上迟到人数
        }
    """
    from core.models.daily_attendance import DailyAttendance  # 导入考勤模型
    from core.models.student_class_enrollment import StudentClassEnrollment  # 导入学生班级关联模型

    # 1. 获取班级内所有学生ID
    class_students = StudentClassEnrollment.objects.filter(class_id=classid).values_list('student_id', flat=True)
    if not class_students:
        return {'morning_late': 0, 'afternoon_late': 0, 'evening_late': 0}

    # 2. 查询指定日期的考勤记录（仅筛选本班学生）
    attendance_records = DailyAttendance.objects.filter(
        student_id__in=class_students,
        date=date
    ).values('morning_attendance', 'afternoon_attendance', 'evening_attendance')

    # 3. 统计各时间段考勤状态（假设False表示迟到，根据实际业务逻辑调整判断条件）
    morning_late_count = sum(1 for record in attendance_records if not record['morning_attendance'])
    afternoon_late_count = sum(1 for record in attendance_records if not record['afternoon_attendance'])
    evening_late_count = sum(1 for record in attendance_records if not record['evening_attendance'])

    return {
        'morning_late': morning_late_count,
        'afternoon_late': afternoon_late_count,
        'evening_late': evening_late_count
    }


'''周分析视图''' 
def week_manage(request, classid, strdate):
    """
    分析指定班级在某周内每天的迟到次数，并将结果渲染到周分析页面。

    :param request: 请求对象，包含当前请求的相关信息。
    :param classid: 班级的 ID，用于筛选指定班级的数据。
    :param strdate: 表示周起始日期的字符串，用于确定分析的周范围。
    :return: 渲染后的周分析页面，包含班级 ID、班级名称、日期列表和每天的迟到次数。
    """
    # 获取指定 ID 的班级信息
    classes = ClassInfo.objects.filter(id=classid).first()
    weekday_list = []
    attendance_list = []
    # 获取指定日期所在周的所有日期
    week_dates = get_week_dates(strdate)
    for day in week_dates:
        # 将日期对象格式化为字符串
        date_str = day.strftime('%Y-%m-%d')
        weekday_list.append(date_str)
        # 获取指定班级在该日期的日常考勤和任务统计信息
        attendance = get_daily_attendance_and_task_stats(classid, date_str)
        # 统计该日期的迟到总次数
        count = attendance['late_stats']['morning'] + attendance['late_stats']['afternoon'] + attendance['late_stats']['cleaning_task']
        attendance_list.append(count)
    print(attendance_list)
    return render(request, 'classmanage/week_manage.html', {
        'classid': classid,
        'classname': classes, 'strdate': strdate,
        'attendance_list': {
            'attendance_list': attendance_list,
            'week_dates': weekday_list,
            'attendance_list': attendance_list
        }
    })

"""
月分析视图 - 展示班级月度管理数据
"""
def month_manage(request,classid,strdate):
    classes=ClassInfo.objects.filter(id=classid).first()

    print(classes)
    return render(request, 'classmanage/month_attendance.html', {'classid':classid,'classname':classes,'strdate':strdate})


'''
学期分析视图
'''
def term_manage(request,classid):
    classes=ClassInfo.objects.filter(id=classid).first()
    print(classes)
    today = date.today().strftime('%Y-%m-%d')
    return render(request, 'classmanage/term_attendance.html',{'classid':classid,'classname':classes, 'strdate': today})



class LeaveRequestListView(ListView):
    """
    用于展示请假申请列表的视图类。
    使用 Django 的 ListView 实现，从数据库中获取所有请假申请记录，
    并将这些记录传递给指定的模板进行渲染展示。
    
    Attributes:
        model (class): 指定使用的模型为 LeaveRequest，用于获取请假申请数据。
        template_name (str): 指定渲染的模板文件名为 'leave_request_list.html'。
        context_object_name (str): 指定传递给模板的上下文变量名为 'leave_requests'。
    """
    model = LeaveRequest
    template_name = 'leave_request/leave_request_list.html'
    context_object_name = 'leave_requests'


class LeaveRequestForm(BaseBootstrapForm):
    class Meta:
        model = LeaveRequest
        fields = '__all__'

class LeaveRequestCreateView(CreateView):
    model = LeaveRequest
    form_class = LeaveRequestForm
    template_name = 'leave_request/leave_request_form.html'
    success_url = reverse_lazy('leave_request_list')


class LeaveRequestUpdateView(UpdateView):
    model = LeaveRequest
    form_class = LeaveRequestForm
    template_name = 'leave_request/leave_request_form.html'
    success_url = reverse_lazy('leave_request_list')


class LeaveRequestDeleteView(DeleteView):
    model = LeaveRequest
    template_name = 'leave_request_confirm_delete.html'
    success_url = reverse_lazy('leave_request_list')


class DisciplineTypeListView(ListView):
    model = DisciplineType
    template_name = 'discipline_record/discipline_type_list.html'
    context_object_name = 'discipline_types'


class DisciplineTypeForm(BaseBootstrapForm):
    class Meta:
        model = DisciplineType
        fields = '__all__'

class DisciplineTypeCreateView(CreateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='create',
            content_type='DisciplineType',
            object_id=self.object.id,
            object_name=self.object.name,
            request=self.request,
            details=f'创建纪律类型: {self.object.name}'
        )
        return response
    model = DisciplineType
    form_class = DisciplineTypeForm
    template_name = 'discipline_record/discipline_type_form.html'
    success_url = reverse_lazy('core:discipline_type_list')


class DisciplineTypeUpdateView(UpdateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='update',
            content_type='DisciplineType',
            object_id=self.object.id,
            object_name=self.object.name,
            request=self.request,
            details=f'更新纪律类型: {self.object.name}'
        )
        return response
    model = DisciplineType
    form_class = DisciplineTypeForm
    template_name = 'discipline_record/discipline_type_form.html'
    success_url = reverse_lazy('core:discipline_type_list')


class DisciplineTypeDeleteView(DeleteView):
    def delete(self, request, *args, **kwargs):
        discipline_type = self.get_object()
        log_operation(
            user=request.user,
            operation_type='delete',
            content_type='DisciplineType',
            object_id=discipline_type.id,
            object_name=discipline_type.name,
            request=request,
            details=f'删除纪律类型: {discipline_type.name}'
        )
        return super().delete(request, *args, **kwargs)
    model = DisciplineType
    template_name = 'discipline_type_confirm_delete.html'
    success_url = reverse_lazy('core:discipline_type_list')


class DisciplineRecordListView(ListView):
    model = DisciplineRecord
    template_name = 'discipline_record/discipline_record_list.html'
    context_object_name = 'discipline_records'
    ordering = ['-happened_at']


class DisciplineRecordForm(BaseBootstrapForm):
    class Meta:
        model = DisciplineRecord
        fields = '__all__'

class DisciplineRecordCreateView(CreateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='create',
            content_type='DisciplineRecord',
            object_id=self.object.id,
            object_name=f'{self.object.student.name} - {self.object.discipline_type.name}',
            request=self.request,
            details=f'创建纪律记录: {self.object.student.name} {self.object.discipline_type.name}'
        )
        return response
    model = DisciplineRecord
    form_class = DisciplineRecordForm
    template_name = 'discipline_record/discipline_record_form.html'
    success_url = reverse_lazy('core:discipline_record_list')


class DisciplineRecordUpdateView(UpdateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='update',
            content_type='DisciplineRecord',
            object_id=self.object.id,
            object_name=f'{self.object.student.name} - {self.object.type.name}',
            request=self.request,
            details=f'更新纪律记录: {self.object.student.name} {self.object.type.name}'
        )
        return response
    model = DisciplineRecord
    form_class = DisciplineRecordForm
    template_name = 'discipline_record/discipline_record_form.html'
    success_url = reverse_lazy('core:discipline_record_list')


class DisciplineRecordDeleteView(DeleteView):
    def delete(self, request, *args, **kwargs):
        record = self.get_object()
        log_operation(
            user=request.user,
            operation_type='delete',
            content_type='DisciplineRecord',
            object_id=record.id,
            object_name=f'{record.student.name} - {record.type.name}',
            request=request,
            details=f'删除纪律记录: {record.student.name} {record.type.name}'
        )
        return super().delete(request, *args, **kwargs)
    model = DisciplineRecord
    template_name = 'discipline_record/discipline_record_confirm_delete.html'
    success_url = reverse_lazy('core:discipline_record_list')


class DisciplineAppealListView(ListView):
    model = DisciplineAppeal
    template_name = 'discipline_record/discipline_appeal_list.html'
    context_object_name = 'discipline_appeals'


class DisciplineAppealForm(BaseBootstrapForm):
    class Meta:
        model = DisciplineAppeal
        fields = '__all__'

class DisciplineAppealCreateView(CreateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='create',
            content_type='DisciplineAppeal',
            object_id=self.object.id,
            object_name=f'申诉-{self.object.discipline_record.id}',
            request=self.request,
            details=f'创建纪律申诉: {self.object.reason[:50]}'
        )
        return response
    model = DisciplineAppeal
    form_class = DisciplineAppealForm
    template_name = 'discipline_appeal_form.html'
    success_url = reverse_lazy('discipline_appeal_list')


class DisciplineAppealUpdateView(UpdateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='update',
            content_type='DisciplineAppeal',
            object_id=self.object.id,
            object_name=f'申诉-{self.object.discipline_record.id}',
            request=self.request,
            details=f'更新纪律申诉: {self.object.reason[:50]}'
        )
        return response
    model = DisciplineAppeal
    form_class = DisciplineAppealForm
    template_name = 'discipline_record/discipline_appeal_form.html'
    success_url = reverse_lazy('discipline_appeal_list')


class DisciplineAppealDeleteView(DeleteView):
    def delete(self, request, *args, **kwargs):
        appeal = self.get_object()
        log_operation(
            user=request.user,
            operation_type='delete',
            content_type='DisciplineAppeal',
            object_id=appeal.id,
            object_name=f'申诉-{appeal.discipline_record.id}',
            request=self.request,
            details=f'删除纪律申诉: {appeal.reason[:50]}'
        )
        return super().delete(request, *args, **kwargs)
    model = DisciplineAppeal
    template_name = 'discipline_record/discipline_appeal_confirm_delete.html'
    success_url = reverse_lazy('discipline_appeal_list')


class HonorTypeListView(ListView):
    model = HonorType
    template_name = 'honor/honor_type_list.html'
    context_object_name = 'honor_types'

class HonorTypeForm(BaseBootstrapForm):
    class Meta:
        model = HonorType
        fields = '__all__'

class HonorTypeCreateView(CreateView):
    model = HonorType
    form_class = HonorTypeForm
    template_name = 'honor/honor_type_form.html'
    success_url = reverse_lazy('core:honor_type_list')

class HonorTypeUpdateView(UpdateView):
    model = HonorType
    form_class = HonorTypeForm
    template_name = 'honor/honor_type_form.html'
    success_url = reverse_lazy('core:honor_type_list')

class HonorTypeDeleteView(DeleteView):
    model = HonorType
    template_name = 'honor/honor_type_confirm_delete.html'
    success_url = reverse_lazy('core:honor_type_list')


class HonorRecordListView(ListView):
    model = HonorRecord
    template_name = 'honor/honor_record_list.html'
    context_object_name = 'honor_records'


class HonorRecordForm(BaseBootstrapForm):
    class Meta:
        model = HonorRecord
        fields = '__all__'

class HonorRecordCreateView(CreateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='create',
            content_type='HonorRecord',
            object_id=self.object.id,
            object_name=f'{self.object.student.name} - {self.object.title}',
            request=self.request,
            details=f'创建表彰记录: {self.object.student.name} {self.object.honor_type.name}'
        )
        return response
    model = HonorRecord
    form_class = HonorRecordForm
    template_name = 'honor/honor_record_form.html'
    success_url = reverse_lazy('core:honor_record_list')


class HonorRecordUpdateView(UpdateView):
    def form_valid(self, form):
        response = super().form_valid(form)
        log_operation(
            user=self.request.user,
            operation_type='update',
            content_type='HonorRecord',
            object_id=self.object.id,
            object_name=f'{self.object.student.name} - {self.object.title}',
            request=self.request,
            details=f'更新表彰记录: {self.object.student.name} {self.object.honor_type.name}'
        )
        return response
    model = HonorRecord
    form_class = HonorRecordForm
    template_name = 'honor/honor_record_form.html'
    success_url = reverse_lazy('core:honor_record_list')


class HonorRecordDeleteView(DeleteView):
    def delete(self, request, *args, **kwargs):
        record = self.get_object()
        log_operation(
            user=self.request.user,
            operation_type='delete',
            content_type='HonorRecord',
            object_id=record.id,
            object_name=f'{record.student.name} - {record.title}',
            request=request,
            details=f'删除表彰记录: {record.student.name} {record.honor_type.name}'
        )
        return super().delete(request, *args, **kwargs)
    model = HonorRecord
    template_name = 'honor_record_confirm_delete.html'
    success_url = reverse_lazy('core:honor_record_list')

